package utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;

import cn.hutool.core.util.RandomUtil;
import utils.handlers.CustomHeadColumnWidthStyleStrategy;
import utils.style.WishExcelStyle;

public class WishExcel
{
	public static ExcelWriter getExcelWriter(String fileName)
	{
		ExcelWriterBuilder excelWriterBuild = EasyExcel.write(fileName);
		return excelWriterBuild.build();
	}

	private static <T> WriteSheet getWriteSheet(String sheetName)
	{
		return EasyExcel.writerSheet(sheetName).registerWriteHandler(WishExcelStyle.getDefaultStyle()).registerWriteHandler(WishExcelStyle.getHeadStyle()).build();
	}

	public static void write(ExcelWriter excelWriter, WishModule<?> wishWriteTable)
	{
		write(excelWriter, Arrays.asList(wishWriteTable));
	}

	public static void write(ExcelWriter excelWriter, List<WishModule<?>> wishWriteTables)
	{
		Map<String, List<WishModule<?>>> map = LambdaUtils.groupby(wishWriteTables, x -> x.getSheetName());
		map.forEach((sheetName, list) -> {
			WishModule<?> module = list.get(0);
			WriteSheet writeSheet = getWriteSheet(sheetName);
			writeSheet.getCustomWriteHandlerList().add(new CustomHeadColumnWidthStyleStrategy(module.getLeafs()));
			writeSheet.setHead(module.getHeaders());
			for (int i = 0; i < list.size(); i++)
			{
				module = list.get(i);
				Integer number = module.getNumber();
				if (number == null)
				{
					number = RandomUtil.randomInt(0, Integer.MAX_VALUE);
				}
				WriteTable writeTable = EasyExcel.writerTable(number).needHead(Boolean.FALSE).build();
				writeTable.setCustomWriteHandlerList(module.getWriteHandlers());
				excelWriter.write(module.getDatas(), writeSheet, writeTable);
			}
		});
	}

	// 多个sheet写入*
	public static ExcelWriter write(String fileName, List<WishModule<?>> wishWriteTables, boolean... autoClose)
	{
		ExcelWriter excelWriter = getExcelWriter(fileName);
		write(excelWriter, wishWriteTables);
		if (autoClose == null || autoClose.length == 0 || autoClose[0])
		{
			excelWriter.close();
		}
		return excelWriter;
	}

	// 单个sheet，多个table*
	public static <T> ExcelWriter write(String fileName, String sheetName, List<WishModule<?>> wishWriteModules, boolean... autoClose)
	{
		if (wishWriteModules.isEmpty())
		{
			return null;
		}
		WishModule<?> module = wishWriteModules.get(0);

		ExcelWriter excelWriter = getExcelWriter(fileName);
		WriteSheet writeSheet = getWriteSheet(sheetName);

		writeSheet.getCustomWriteHandlerList().add(new CustomHeadColumnWidthStyleStrategy(module.getLeafs()));
		writeSheet.setHead(module.getHeaders());

		for (int i = 0; i < wishWriteModules.size(); i++)
		{
			WriteTable writeTable = EasyExcel.writerTable(i).needHead(Boolean.FALSE).build();
			writeTable.setCustomWriteHandlerList(wishWriteModules.get(i).getWriteHandlers());
			excelWriter.write(wishWriteModules.get(i).getDatas(), writeSheet, writeTable);
		}
		if (autoClose == null || autoClose.length == 0 || autoClose[0])
		{
			excelWriter.close();
		}
		return excelWriter;
	}

	// 单个sheet，单个table
	public static <T> void write(String fileName, List<WishColumn<?>> headers, List<T> datas, List<WriteHandler> writeHandlers, String sheetName)
	{
		WishModule<?> module = new WishModule<>(sheetName, headers, () -> datas);
		module.setWriteHandlers(writeHandlers);
		write(fileName, sheetName, Arrays.asList(module));
	}

	// 单个sheet，单个table*
	public static <T> void write(String fileName, String sheetName, List<WishColumn<?>> headers, List<T> datas)
	{
		write(fileName, headers, datas, new ArrayList<>(), sheetName);
	}

	public static <T> void write(String fileName, String sheetName, List<WishColumn<?>> headers, List<T> datas, List<int[]> merges)
	{
		List<WriteHandler> writeHandlers = new ArrayList<>();
		if (merges != null)
		{
			for (int[] items : merges)
			{
				writeHandlers.add(new OnceAbsoluteMergeStrategy(items[0], items[1], items[2], items[3]));
			}
		}
		write(fileName, headers, datas, writeHandlers, sheetName);
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 单个sheet写入,最原始的写入
	public static void write(String fileName, String sheetName, List<List<String>> headers, List<List<Object>> datas, List<WriteHandler> writeHandlers, boolean... autoClose)
	{
		ExcelWriter excelWriter = getExcelWriter(fileName);
		WriteSheet writeSheet = getWriteSheet(sheetName);
		writeSheet.setHead(headers);
		if (writeHandlers != null && !writeHandlers.isEmpty())
		{
			writeSheet.getCustomWriteHandlerList().addAll(writeHandlers);
		}
		excelWriter.write(datas, writeSheet);
		if (autoClose == null || autoClose.length == 0 || autoClose[0])
		{
			excelWriter.close();
		}
	}
}
